﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AcademiaEntidades;
using System.Data.SqlClient;
using System.Data;

namespace AcademiaDAO
{
    public class AlumnoDAO
    {
        public static List<Alumno> ObtenerTodos(string orden, string nombre, string apellido, int? legajo, DateTime? fechaInscripcionDesde, DateTime? fechaInscripcionHasta)
        {
            List<Alumno> alumnos = new List<Alumno>();

            try
            {
                // la conexión se cierra automáticamente con "using"
                using (SqlConnection conn = AccesoDato.Conectar())
                {
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;

                    /* string sql = @"SELECT TOP 1000 FROM Alumnos"; */
                    StringBuilder sb = new StringBuilder(@"SELECT a.IdAlumno, a.Legajo, a.Nombre, a.Apellido, td.IdTipoDocumento, a.NumeroDocumento, a.Telefono, a.FechaInscripcion, td.Descripcion FROM Alumno a ");
                    sb.Append("INNER JOIN TipoDocumento td ON a.IdTipoDocumento = td.IdTipoDocumento ");
                    sb.Append("WHERE 1 = 1");

                    // se arma el string de la consulta según los filtros
                    if (!string.IsNullOrEmpty(nombre))
                    {
                        sb.Append(" AND Nombre LIKE @Nombre");
                        cmd.Parameters.AddWithValue("@Nombre", "%" + nombre + "%");
                    }

                    if (!string.IsNullOrEmpty(apellido))
                    {
                        sb.Append(" AND Apellido LIKE @Apellido");
                        cmd.Parameters.AddWithValue("@Apellido", "%" + apellido + "%");
                    }

                    if (legajo.HasValue)
                    {
                        sb.Append(" AND Legajo = @Legajo");
                        cmd.Parameters.AddWithValue("@Legajo", legajo);
                    }

                    if (fechaInscripcionDesde.HasValue)
                    {
                        sb.Append(" AND FechaInscripcion >= @FechaInsDesde");
                        cmd.Parameters.AddWithValue("@FechaInsDesde", fechaInscripcionDesde);
                    }

                    if (fechaInscripcionHasta.HasValue)
                    {
                        sb.Append(" AND FechaInscripcion <= @FechaInsHasta");
                        cmd.Parameters.AddWithValue("@FechaInsHasta", fechaInscripcionHasta);
                    }

                    if (!string.IsNullOrEmpty(orden))
                    {
                        sb.Append(" ORDER BY ").Append(orden);
                    }

                    cmd.CommandText = sb.ToString();

                    conn.Open();
                    SqlDataReader dr = cmd.ExecuteReader();

                    while (dr.Read())
                    {
                        alumnos.Add(MapearEntidad(dr));
                    }
                }
                return alumnos;
            }
            catch (SqlException ex)
            {
                throw new Exception("No se pudo obtener los datos de los alumnos"); ;
            }
        }

        public static void Grabar(Alumno a)
        {
            try
            {
                using (SqlConnection conn = AccesoDato.Conectar())
                {
                    StringBuilder sql = new StringBuilder(string.Empty);
                    SqlCommand cmd = new SqlCommand();
                    cmd.Connection = conn;
                    conn.Open();

                    // se obtiene el siguiente legajo de la tabla auxiliar
                    sql.Append("SELECT Legajo FROM AlumnoLegajoAux");
                    cmd.CommandText = sql.ToString();

                    int legajo = int.Parse(cmd.ExecuteScalar().ToString()); // no hace falta actualizar la tabla auxiliar, se actualiza sola con un trigger en la base de datos
                    a.Legajo = legajo;

                    // no se hacen validaciones para valores nulos porque todos los valores deben venir con valor
                    cmd.Parameters.AddWithValue("@Nombre", a.Nombre);
                    cmd.Parameters.AddWithValue("@Apellido", a.Apellido);
                    cmd.Parameters.AddWithValue("@Telefono", a.Telefono);

                    if (a.IdAlumno == 0) // si es un alta...
                    {
                        sql = new StringBuilder("INSERT INTO Alumno(Legajo, Nombre, Apellido, IdTipoDocumento, NumeroDocumento, Telefono, FechaInscripcion) VALUES(@Legajo, @Nombre, @Apellido, @IdTipoDoc, @NroDoc, @Telefono, @FechaInscripcion)");
                        cmd.Parameters.AddWithValue("@Legajo", legajo);
                        cmd.Parameters.AddWithValue("@IdTipoDoc", a.TipoDocumento.IdTipoDocumento);
                        cmd.Parameters.AddWithValue("@NroDoc", a.NumeroDocumento);
                        cmd.Parameters.AddWithValue("@FechaInscripcion", a.FechaInscripcion);
                    }
                    else // si es una modificación...
                    {
                        sql = new StringBuilder("UPDATE Alumno SET Nombre=@Nombre, Apellido=@Apellido, Telefono=@Telefono");
                        if (a.TipoDocumento != null)
                        {
                            sql.Append(", IdTipoDocumento=@IdTipoDoc");
                            cmd.Parameters.AddWithValue("@IdTipoDoc", a.TipoDocumento.IdTipoDocumento);
                        }

                        if (a.NumeroDocumento != null)
                        {
                            sql.Append(", NumeroDocumento=@NroDoc");
                            cmd.Parameters.AddWithValue("@NroDoc", a.NumeroDocumento);
                        }
                        sql.Append(" WHERE IdAlumno=@IdAlumno");
                        cmd.Parameters.AddWithValue("@IdAlumno", a.IdAlumno);
                    }

                    cmd.CommandText = sql.ToString();
                    int res = cmd.ExecuteNonQuery();

                    if (res == 0)   // si hay 0 filas modificadas...
                    {
                        throw new Exception("No se pudo grabar el alumno");
                    }
                    else if (a.IdAlumno == 0)    // si se guardó el alumno en alta...
                    {
                        sql = new StringBuilder("SELECT IDENT_CURRENT('Alumno')");
                        cmd.CommandText = sql.ToString();
                        /* string id = cmd.ExecuteScalar().ToString(); */
                        int id = int.Parse(cmd.ExecuteScalar().ToString());
                        a.IdAlumno = id;
                    }
                }
            }
            catch (SqlException ex)
            {
                string mensaje = string.Empty;
                switch (ex.Number)
                {
                    case 2601: mensaje = string.Format("Ya existe un alumno con {0} {1}", a.TipoDocumento.Descripcion, a.NumeroDocumento); break;
                    default: mensaje = "No se pudo grabar el alumno";
                        break;
                }
                throw new Exception(mensaje);
            }
        }

        public static Alumno ObtenerPorId(int id)
        {
            try
            {
                Alumno alumno = null;
                using (SqlConnection conn = AccesoDato.Conectar())
                {
                    StringBuilder sb = new StringBuilder(@"SELECT a.IdAlumno, a.Legajo, a.Nombre, a.Apellido, td.IdTipoDocumento, a.NumeroDocumento, a.Telefono, a.FechaInscripcion, td.Descripcion FROM Alumno a ");
                    sb.Append("INNER JOIN TipoDocumento td ON a.IdTipoDocumento = td.IdTipoDocumento WHERE a.IdAlumno = @IdAlumno");
                    SqlCommand cmd = new SqlCommand(sb.ToString(), conn);
                    cmd.Parameters.AddWithValue("@IdAlumno", id);
                    conn.Open();
                    SqlDataReader dr = cmd.ExecuteReader();
                    if (dr.Read())
                    {
                        alumno = MapearEntidad(dr);
                    }
                }
                return alumno;
            }
            catch (SqlException ex)
            {
                throw new Exception("No se pudo recuperar el alumno");
            }
        }
        //Agregue un metodo que busque por legajo y devuelva el idAlumno
        public static int obtenerIdXLegajo(int legajo)
        {
            int idAlumno;
            SqlConnection cn = null;
            try
            {
                cn = AccesoDato.dameConexion();
                cn.Open();
                SqlCommand cmd = new SqlCommand();
                string sql = "select IdAlumno from Alumno where Legajo = @legajo";
                cmd.Parameters.Add(new SqlParameter("@legajo", legajo));
                cmd.CommandText = sql;
                cmd.Connection = cn;
                //SqlDataReader dr = cmd.ExecuteReader();
                idAlumno = int.Parse(cmd.ExecuteScalar().ToString());//Tendria que devolver el id

                //if (dr.Read())
                //{
                //    idAlumno = int.Parse(dr["IdAlumno"].ToString());

                //}
                //dr.Close();
            }
            catch (SqlException ex)
            {
                throw new Exception("No se pudo obtener los datos del Alumno");//El metodo que lo invoque debera tratar la exepcion
            }
            finally//Si la conexion se pudo abrir hay que cerrarla
            {
                if (cn.State == ConnectionState.Open)
                    cn.Close();
            }
            return idAlumno;
        }//Fin del metodo obtenerIdXLegajo

        public static void Eliminar(int id)
        {
            try
            {
                using (SqlConnection conn = AccesoDato.Conectar())
                {
                    string sql = "DELETE FROM Alumno WHERE IdAlumno = @IdAlumno";
                    SqlCommand cmd = new SqlCommand(sql, conn);
                    cmd.Parameters.AddWithValue("@IdAlumno", id);
                    conn.Open();
                    int res = cmd.ExecuteNonQuery();

                    if (res != 1)
                    {
                        throw new Exception("No se pudo eliminar el alumno");
                    }
                }
            }
            catch (SqlException ex)
            {
                throw new Exception("No se pudo eliminar el alumno");
            }
        }

        public static Alumno ObtenerPorLegajo(int legajo)
        {
            Alumno alumno = null;
            List<Alumno> alumnos = ObtenerTodos(null, null, null, legajo, null, null);
            if (alumnos.Count > 0 && alumnos.First() != null)
            {
                alumno = alumnos.First();
            }
            return alumno;
        }

        private static Alumno MapearEntidad(SqlDataReader dr)
        {
            int id = dr.GetInt32(0);
            int leg = dr.GetInt32(1);
            string nom = dr.GetString(2);
            string ape = dr.GetString(3);
            int idTipoDoc = dr.GetInt32(4);
            string nroDoc = dr.GetString(5);
            string telefono = dr.GetString(6);
            DateTime fechaInscripcion = dr.GetDateTime(7);
            string tipoDocDesc = dr.GetString(8);
            return new Alumno(id, leg, nom, ape, nroDoc, new TipoDocumento(idTipoDoc, tipoDocDesc), telefono, fechaInscripcion);
        }
    }
}
